#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/use_awaitable.hpp>

namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::asio;
using tcp = boost::asio::ip::tcp;

net::awaitable<void> async_handle_request(tcp::socket socket) {
    beast::flat_buffer buffer;
    http::request <http::string_body> request;
    boost::system::error_code ec;

    // Asynchronously read the request
    co_await http::async_read(socket, buffer, request, boost::asio::use_awaitable);

    // Process the request
    http::response <http::string_body> response;
    response.version(request.version());
    response.result(http::status::ok);
    response.set(http::field::server, "Boost Beast Server");
    response.set(http::field::content_type, "text/plain");
    response.keep_alive(request.keep_alive());
    response.body() = "Hello, World!";
    response.prepare_payload();

    // Asynchronously write the response
    co_await http::async_write(socket, response, boost::asio::use_awaitable);

    // Shutdown the socket
    socket.shutdown(tcp::socket::shutdown_send, ec);
    if (ec) {
        std::cerr << "Error in shutdown: " << ec.message() << std::endl;
    }
}

net::awaitable<void> async_accept(tcp::acceptor &acceptor) {
    while (true) {
        tcp::socket socket = co_await acceptor.async_accept(boost::asio::use_awaitable);
        boost::asio::co_spawn(socket.get_executor(), async_handle_request(std::move(socket)), net::detached);
    }
}

int main() {
    try {
        net::io_context ioc(1);
        tcp::endpoint endpoint(tcp::v4(), 8080);
        tcp::acceptor acceptor(ioc, endpoint);
        boost::asio::co_spawn(acceptor.get_executor(), async_accept(acceptor), net::detached);
        ioc.run();
    } catch (const std::exception &e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}
